package org.mozhu.mboot.core.i18n;

import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
import java.util.Set;

/**
 * 先从Session中读取Locale，然后尝试从Cookies中读取 Change Locale时，Cookies和Session中都存一份
 * 
 * @author ZhangPei
 * 
 */
public class CookieSessionLocaleResolver extends CookieLocaleResolver implements LocaleResolver {

	public static final String LOCALE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".LOCALE";

	private String localeSessionAttributeName = LOCALE_SESSION_ATTRIBUTE_NAME;

	private final PathMatcher pathMatcher = new AntPathMatcher();

	private Set<String> skipResolveLocaleFromSessionUrls;

	protected Locale resolveLocaleFromSession(HttpServletRequest request) {
		return (Locale) WebUtils.getSessionAttribute(request, localeSessionAttributeName);
	}

	protected void setLocaleToSession(HttpServletRequest request, HttpServletResponse response, Locale locale) {
		WebUtils.setSessionAttribute(request, localeSessionAttributeName, locale);
	}

	@Override
	public Locale resolveLocale(HttpServletRequest request) {
		Locale locale = null;
		if (!needSkipToResolveFromSession(request)) {
			locale = resolveLocaleFromSession(request);
			if (locale != null) {
				return locale;
			}
		}
		locale = super.resolveLocale(request);
		if (locale != null) {
			setLocaleToSession(request, null, locale);
		}
		return locale;
	}

	@Override
	public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
		super.setLocale(request, response, locale);
		setLocaleToSession(request, response, locale);
	}

	public void setLocaleSessionAttributeName(String localeSessionAttributeName) {
		this.localeSessionAttributeName = localeSessionAttributeName;
	}

	private boolean needSkipToResolveFromSession(HttpServletRequest request) {
		String servletPath = request.getServletPath();
		if (CollectionUtils.isEmpty(skipResolveLocaleFromSessionUrls)) {
			return false;
		}
		for (String exclusion : skipResolveLocaleFromSessionUrls) {
			if (pathMatcher.match(exclusion, servletPath)) {
				return true;
			}
		}
		return false;
	}

	public void setSkipResolveLocaleFromSessionUrls(Set<String> skipResolveLocaleFromSessionUrls) {
		this.skipResolveLocaleFromSessionUrls = skipResolveLocaleFromSessionUrls;
	}

}
